package tools.settings;

import datatypes.FrequencyRange;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.filechooser.FileSystemView;
import javax.xml.transform.TransformerConfigurationException;
import jxl.Cell;
import jxl.Workbook;
import jxl.read.biff.BiffException;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;

import org.w3c.dom.Element;

/**
 *
 * @author Lynne Vandousselaere
 */
public class SettingsAdapter {

    // Static singleton object of this class.
    private static SettingsAdapter sa;

    // Map containing all sfile settings.
    private Settings settings = null;
    private ArrayList<File> flist = new ArrayList<File>();
    private File default_folder = FileSystemView.getFileSystemView().getDefaultDirectory();

    /**
     * <p>
     * Returns the singleton instance of this class.
     * </p>
     *
     * @return the singleton instance of "CoverageAdapter"
     */
    public static SettingsAdapter getInstance() {
        if (sa == null)
            sa = new SettingsAdapter();
        return sa;
    }

    private SettingsAdapter() {
    }

    public void clear() {
        settings.clear();
        flist.clear();
        default_folder = FileSystemView.getFileSystemView().getDefaultDirectory();
    }

    public File getDefault_folder() {
        return default_folder;
    }

    public Collection<File> getTechnologyFiles() {
        return settings == null ? null : settings.getLocations();
    }

    public void setDefaultFolder(File folder) {
        default_folder = folder;
    }

    /**
     * <p>
     * Returns the Settings, for the given sfile.
     * </p>
     *
     * @return an instance of "Settings"
     */
    public void addSettings(File sfile) throws SettingsReaderException {
        if (sfile == null || flist.contains(sfile))
            return;

        if (!sfile.canRead())
            throw new SettingsReaderException("Can't read the given file. Check if file exists and is readable");

        if (settings == null)
            settings = new MapSettings();

        settings.readSettings(sfile);
        flist.add(sfile);
    }

    /**
     * <p>
     * Returns the Settings, for the given sfile.
     * </p>
     *
     * @return an instance of "Settings", or null if no settings are available.
     */
    public void addSettings(Collection<File> fcoll) throws SettingsReaderException {
        if (fcoll == null)
            return;

        for (Iterator<File> it = fcoll.iterator(); it.hasNext();)
            addSettings(it.next());
    }

    public void addSettings(File[] sfile) throws SettingsReaderException {
        if (sfile == null)
            return;

        for (int f = 0; f < sfile.length; f++)
            addSettings(sfile[f]);
    }

    /**
     *
     * @return retrieve all current settings.
     */
    public Settings getSettings() {
        return settings;
    }

    public Vector<FrequencyRange> getFrequencyRange() {
        Vector<FrequencyRange> v = new Vector<FrequencyRange>();
        String s = settings.getSettingsValue("technology");
        if (s.equalsIgnoreCase("umts"))
            v.add(new FrequencyRange(2000, 2200));
        else if (s.equalsIgnoreCase("gsm")) {
            v.add(new FrequencyRange(850, 950));
            v.add(new FrequencyRange(1700, 1900));
        } else if (s.equalsIgnoreCase("lte")) {
            v.add(new FrequencyRange(0,0));
        } else if (s.equalsIgnoreCase("wimax")){
            v.add(new FrequencyRange(0,0));
        } else if (s.equalsIgnoreCase("wifi")){
            v.add(new FrequencyRange(0,0));
        } else if (s.equalsIgnoreCase("lte-a")){
            v.add(new FrequencyRange(0,0));
        }
        else
            v.add(new FrequencyRange(0, 4000));
//            return null;
        return v;
    }
    

    public String getTechnologyName() {
        return settings.getSettingsValue("technology");
       }

    public void createXML(File file) throws IOException, BiffException, ParserConfigurationException, TransformerConfigurationException, TransformerException {
        Workbook settingsExcel = Workbook.getWorkbook(file);
        
        Cell technology_ = settingsExcel.findCellByName("technology");
        Cell plm_ = settingsExcel.findCellByName("PLdense");
        Cell rangefactor_ = settingsExcel.findCellByName("rangefactor");
        Cell coverage_requirement_ = settingsExcel.findCellByName("coverage_requirement");
        Cell indoor_ = settingsExcel.findCellByName("indoor");
        Cell urban_correction_ = settingsExcel.findCellByName("urban_correction");
        Cell bs_feeder_loss_ = settingsExcel.findCellByName("bs_feeder_loss");
        Cell bs_diversity_gain_ = settingsExcel.findCellByName("bs_diversity_gain");
        Cell bs_soft_handover_gain_ = settingsExcel.findCellByName("bs_soft_handover_gain");
        Cell ms_height_ = settingsExcel.findCellByName("ms_height");
        Cell ms_tx_power_ = settingsExcel.findCellByName("ms_tx_power");
        Cell ms_antenna_gain_ = settingsExcel.findCellByName("ms_antenna_gain");
        Cell ms_feeder_loss_ = settingsExcel.findCellByName("ms_feeder_loss");
        Cell ms_body_loss_ = settingsExcel.findCellByName("ms_body_loss");
        Cell ms_diverstiy_gain_ = settingsExcel.findCellByName("ms_diversity_gain");
        Cell ms_fast_fading_margin_ = settingsExcel.findCellByName("ms_fast_fading_margin");
        Cell ms_soft_handover_gain_ = settingsExcel.findCellByName("ms_soft_handover_gain");
        Cell bs_rcv_sensitivity_ = settingsExcel.findCellByName("bs_rcv_sensitivity");
        Cell bs_noise_figure_ = settingsExcel.findCellByName("bs_noise_figure");
        Cell ms_rcv_sensitivity_ = settingsExcel.findCellByName("ms_rcv_sensitivity");
        Cell ms_noise_figure_ = settingsExcel.findCellByName("ms_noise_figure");

        String plm_edit = "costhata";

        if(plm_.getContents().toLowerCase().contains("cost")){
            plm_edit = "costhata";
        }else if(plm_.getContents().toLowerCase().contains("erceg")){
            plm_edit = "erceg";
        }else if(plm_.getContents().toLowerCase().contains("free")){
            plm_edit = "freespace";
        }else if(plm_.getContents().toLowerCase().contains("wi")){
            plm_edit = "wilos";
        }


        ArrayList modulation = new ArrayList();
        ArrayList rec_sens_dl = new ArrayList();
        ArrayList rec_sens_ul = new ArrayList();
        ArrayList bitrate_dl = new ArrayList();
        ArrayList bitrate_ul = new ArrayList();

        String mod,value_dl,value_ul,value_bdl,value_bul;
        char c = 'B';

        while(!settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(27))).getContents().equals("0")){
            modulation.add(settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(27))).getContents());
            value_dl = settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(28))).getContents();
            value_ul = settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(29))).getContents();
            value_bdl = settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(30))).getContents();
            value_bul = settingsExcel.getCell("Settings!".concat(Character.toString(c)).concat(Integer.toString(31))).getContents();

            rec_sens_dl.add(value_dl);
            rec_sens_ul.add(value_ul);
            bitrate_dl.add(value_bdl);
            bitrate_ul.add(value_bul);
            c++;
        }




        try{
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            //root elements
            Document doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("root");
            doc.appendChild(rootElement);

            Element technology = doc.createElement("technology");
            technology.appendChild(doc.createTextNode(technology_.getContents()));
            rootElement.appendChild(technology);

            Element plm = doc.createElement("PLM");
            plm.appendChild(doc.createTextNode(plm_edit));
            rootElement.appendChild(plm);

            Element rangefactor = doc.createElement("rangefactor");
            rangefactor.appendChild(doc.createTextNode(rangefactor_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(rangefactor);

            Element coverage_requirement = doc.createElement("coverage_requirement");
            coverage_requirement.appendChild(doc.createTextNode(coverage_requirement_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(coverage_requirement);


            Element indoor = doc.createElement("indoor");
            indoor.appendChild(doc.createTextNode(indoor_.getContents()));
            rootElement.appendChild(indoor);

            Element urban_correction = doc.createElement("urban_correction");
            urban_correction.appendChild(doc.createTextNode(urban_correction_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(urban_correction);

            urban_correction.setAttribute("rural", "-5");
            urban_correction.setAttribute("suburban", "0");
            urban_correction.setAttribute("urban", "3");
            urban_correction.setAttribute("dense_urban", "4");

            Element bs_feeder_loss = doc.createElement("bs_feeder_loss");
            bs_feeder_loss.appendChild(doc.createTextNode(bs_feeder_loss_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(bs_feeder_loss);

            bs_feeder_loss.setAttribute("type", "loss");
            bs_feeder_loss.setAttribute("DL", "1");
            bs_feeder_loss.setAttribute("UL", "1");

            Element bs_diversity_gain = doc.createElement("bs_diversity_gain");
            bs_diversity_gain.appendChild(doc.createTextNode(bs_diversity_gain_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(bs_diversity_gain);

            bs_diversity_gain.setAttribute("type", "gain");
            bs_diversity_gain.setAttribute("DL", "0");
            bs_diversity_gain.setAttribute("UL", "1");

            Element bs_soft_handover_gain = doc.createElement("bs_soft_handover_gain");
            bs_soft_handover_gain.appendChild(doc.createTextNode(bs_soft_handover_gain_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(bs_soft_handover_gain);

            bs_soft_handover_gain.setAttribute("type", "gain");
            bs_soft_handover_gain.setAttribute("DL", "0");
            bs_soft_handover_gain.setAttribute("UL", "1");

            Element ms_height = doc.createElement("ms_height");
            ms_height.appendChild(doc.createTextNode(ms_height_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_height);

            Element ms_tx_power = doc.createElement("ms_tx_power");
            ms_tx_power.appendChild(doc.createTextNode(ms_tx_power_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_tx_power);

            ms_tx_power.setAttribute("DL", "0");
            ms_tx_power.setAttribute("UL", "1");

            Element ms_antenna_gain = doc.createElement("ms_antenna_gain");
            ms_antenna_gain.appendChild(doc.createTextNode(ms_antenna_gain_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_antenna_gain);

            ms_antenna_gain.setAttribute("type", "gain");
            ms_antenna_gain.setAttribute("DL", "1");
            ms_antenna_gain.setAttribute("UL", "1");

            Element ms_feeder_loss = doc.createElement("ms_feeder_loss");
            ms_feeder_loss.appendChild(doc.createTextNode(ms_feeder_loss_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_feeder_loss);

            ms_feeder_loss.setAttribute("type", "loss");
            ms_feeder_loss.setAttribute("DL", "1");
            ms_feeder_loss.setAttribute("UL", "1");

            Element ms_body_loss = doc.createElement("ms_body_loss");
            ms_body_loss.appendChild(doc.createTextNode(ms_body_loss_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_body_loss);

            ms_body_loss.setAttribute("type", "loss");
            ms_body_loss.setAttribute("DL", "1");
            ms_body_loss.setAttribute("UL", "1");

            Element ms_diverstiy_gain = doc.createElement("ms_diverstiy_gain");
            ms_diverstiy_gain.appendChild(doc.createTextNode(ms_diverstiy_gain_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_diverstiy_gain);

            ms_diverstiy_gain.setAttribute("type", "gain");
            ms_diverstiy_gain.setAttribute("DL", "1");
            ms_diverstiy_gain.setAttribute("UL", "0");

            Element ms_fast_fading_margin = doc.createElement("ms_fast_fading_margin");
            ms_fast_fading_margin.appendChild(doc.createTextNode(ms_fast_fading_margin_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_fast_fading_margin);

            ms_fast_fading_margin.setAttribute("type", "margin");
            ms_fast_fading_margin.setAttribute("DL", "0");
            ms_fast_fading_margin.setAttribute("UL", "1");

            Element ms_soft_handover_gain = doc.createElement("ms_soft_handover_gain");
            ms_soft_handover_gain.appendChild(doc.createTextNode(ms_soft_handover_gain_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_soft_handover_gain);

            ms_soft_handover_gain.setAttribute("type", "gain");
            ms_soft_handover_gain.setAttribute("DL", "1");
            ms_soft_handover_gain.setAttribute("UL", "0");

            Element bs_rcv_sensitivity = doc.createElement("bs_rcv_sensitivity");
            bs_rcv_sensitivity.appendChild(doc.createTextNode(bs_rcv_sensitivity_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(bs_rcv_sensitivity);

            bs_rcv_sensitivity.setAttribute("DL", "0");
            bs_rcv_sensitivity.setAttribute("UL", "1");

            Element bs_noise_figure = doc.createElement("bs_noise_figure");
            bs_noise_figure.appendChild(doc.createTextNode(bs_noise_figure_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(bs_noise_figure);

            bs_noise_figure.setAttribute("DL", "1");
            bs_noise_figure.setAttribute("UL", "0");

            Element ms_rcv_sensitivity = doc.createElement("ms_rcv_sensitivity");
            ms_rcv_sensitivity.appendChild(doc.createTextNode(ms_rcv_sensitivity_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_rcv_sensitivity);

            ms_rcv_sensitivity.setAttribute("DL", "1");
            ms_rcv_sensitivity.setAttribute("UL", "0");

            Element ms_noise_figure = doc.createElement("ms_noise_figure");
            ms_noise_figure.appendChild(doc.createTextNode(ms_noise_figure_.getContents().replaceAll(",", ".")));
            rootElement.appendChild(ms_noise_figure);

            ms_noise_figure.setAttribute("DL", "1");
            ms_noise_figure.setAttribute("UL", "0");

            int i = 0;

            for(int j = modulation.size()-1;j>=0;j--){
                Element rec_sens_dl_ = doc.createElement("rcv_sens_dl_".concat(Integer.toString(i)));
                rec_sens_dl_.appendChild(doc.createTextNode(((String)rec_sens_dl.get(j)).replaceAll(",", ".")));
                rootElement.appendChild(rec_sens_dl_);
                
                rec_sens_dl_.setAttribute("modulation", (String)modulation.get(j));

            Element rec_sens_ul_ = doc.createElement("rcv_sens_ul_".concat(Integer.toString(i)));
                rec_sens_ul_.appendChild(doc.createTextNode(((String)rec_sens_ul.get(j)).replaceAll(",", ".")));
                rootElement.appendChild(rec_sens_ul_);

                rec_sens_ul_.setAttribute("modulation", (String)modulation.get(j));
                
                Element bitrate_dl_ = doc.createElement("bitrate_dl_".concat(Integer.toString(i)));
                bitrate_dl_.appendChild(doc.createTextNode(((String)bitrate_dl.get(j)).replaceAll(",", ".")));
                rootElement.appendChild(bitrate_dl_);

                bitrate_dl_.setAttribute("modulation", (String)modulation.get(j));

                Element bitrate_ul_ = doc.createElement("bitrate_ul_".concat(Integer.toString(i)));
                bitrate_ul_.appendChild(doc.createTextNode(((String)bitrate_ul.get(j)).replaceAll(",", ".")));
                rootElement.appendChild(bitrate_ul_);

                bitrate_ul_.setAttribute("modulation", (String)modulation.get(j));

                i++;
            }

            //write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result =  new StreamResult(new File("./Input/settings.xml"));
            transformer.transform(source, result);

            System.out.println("Done");
        }catch(ParserConfigurationException pce){
            pce.printStackTrace();
        }catch(TransformerException tfe){
	 tfe.printStackTrace();
     }
        

    }
}
